home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_400
/
406_01
/
atoc
/
function.c
< prev
next >
Wrap
Text File
|
1993-11-09
|
7KB
|
286 lines
/*=========================================================================
ATOC function declarations module
=========================================================================*/
#include <stdio.h>
#include <ctype.h>
#include "atoc.h"
/**/ /* this version requires that function and all args are on one line */
/* #define TESTING */
#define MAXARGS 32 /* max args one function can have */
/*-------------------------------------------------------------------------
local global variables
-------------------------------------------------------------------------*/
PRIVATE char *args[ MAXARGS ] = { /* individual arguments */
NULL
};
PRIVATE char temp[ MAXLINELENGTH ]; /* temp buffer */
/*-------------------------------------------------------------------------
function( s ) looks for function declarations or prototypes and expands or
removes their arguments.
-------------------------------------------------------------------------*/
function( s )
char *s;
{
char *start, *stop, *strchr(), *strrchr();
char *cp, *dp, *malloc();
char *argname();
int ansi_style, i;
if ( isfunction( s ) )
{
start = strchr( s, '(' ) + 1;
stop = strrchr( s, ')' );
if ( strchr( s, ';' ) == NULL ) /* declaration */
{
/* make list of arguments in *args[] */
i = 0;
for ( cp = start; cp < stop; ++cp )
{
while ( cp < stop && isspace( *cp ) )
++cp;
if ( cp < stop )
{
dp = temp;
while ( cp < stop && *cp != ',' )
*dp++ = *cp++;
*dp = '\0';
/* strip trailing spaces */
for ( --dp; dp >= temp && isspace( *dp ); --dp )
*dp = '\0';
if ( ( args[ i ] = malloc( strlen( temp ) + 1 ) ) != NULL )
{
strcpy( args[ i ], temp );
++i;
}
}
}
args[ i ] = NULL;
/* see if ANSI or K&R style */
/* ANSI will have white space within arg */
ansi_style = FALSE;
for ( cp = args[ 0 ]; *cp; ++cp )
if ( isspace( *cp ) )
{
ansi_style = TRUE;
break;
}
if ( ansi_style )
{
/* save any trailing stuff */
strcpy( temp, stop + 1 );
/* remove end of current line */
*start = '\0';
/* rebuild line with arg names */
strcat( buffer, " " );
for ( i = 0; args[ i ]; ++i )
{
if ( i > 0 )
strcat( buffer, ", " );
strcat( buffer, argname( args[ i ] ) );
}
strcat( buffer, " )" );
strcat( buffer, temp );
/* flag that there are args to output */
decflag = TRUE;
}
}
else /* prototype */
{
if ( stop > start )
strcpy( start, stop );
}
}
}
/*-------------------------------------------------------------------------
argname( s ) finds the argument name in s and puts it in a local buffer,
returning a pointer to it.
-------------------------------------------------------------------------*/
PRIVATE char *argname( s )
char *s;
{
static char name[ 80 ];
char *cp, *np, *strchr(), *strtok();
strcpy( name, s ); /* get temp copy */
if ( ( cp = strchr( name, '[' ) ) != NULL ) /* remove any [] */
*cp = '\0';
for ( cp = name; *cp; ++cp ) /* remove all non-id chars */
if ( ! isid( *cp ) )
*cp = ' ';
np = NULL; /* find last valid name */
for ( cp = name; ( cp = strtok( cp, " " ) ) != NULL; cp = NULL )
np = cp;
return( np ); /* return it */
}
/*-------------------------------------------------------------------------
declarations( fo ) outputs all the declaration lines we saved from the
function declaration. Called from outside this module.
-------------------------------------------------------------------------*/
declarations( fo )
FILE *fo;
{
int i;
for ( i = 0; args[ i ]; ++i )
fprintf( fo, "%s;\n", args[ i ] );
args[ 0 ] = NULL;
}
/*-------------------------------------------------------------------------
isfunction( s ) returns TRUE if it thinks this line is a function declaration
or prototype, or FALSE otherwise.
-------------------------------------------------------------------------*/
PRIVATE int isfunction( s )
char *s;
{
char *cp, *strchr(), *strstr();
int pnflag, pnlevel;
int firstid, secondid, whitespace;
/* should have at least one pair of parens with proper nesting */
/* at least two identifiers prior to the opening paren */
/* only certain non-identifier characters allowed */
/* and nothing beyond final nesting paren except semicolon or comments */
pnflag = FALSE;
pnlevel = 0;
firstid = secondid = whitespace = FALSE;
for ( cp = s; *cp; ++cp )
if ( ! isid( *cp ) )
{
if ( *cp == '(' )
{
pnflag = TRUE;
++pnlevel;
}
else if ( *cp == ')' )
{
if ( pnflag && pnlevel > 0 )
{
--pnlevel;
if ( pnlevel == 0 )
{
/* check thru stuff after last nesting paren */
for ( ++cp; *cp; ++cp )
switch( *cp )
{
case '\t':
case ' ':
case ';':
break;
case '/':
if ( *( cp + 1 ) == '*' )
for ( cp += 2; *cp; ++cp )
if ( *cp == '*' && *( cp + 1 ) == '/' )
{
++cp;
break;
}
break;
default:
#ifdef TESTING
printf( "*** NOT A FUNCTION BECAUSE OF <%c> AFTER LAST PAREN ***\n", *cp );
#endif
return( FALSE );
}
break; /* stuff after parens is all ok */
}
}
else
{
#ifdef TESTING
printf( "*** NOT A FUNCTION BECAUSE PAREN NESTING IS BAD ***\n" );
#endif
return( FALSE );
}
}
else if ( isspace( *cp ) )
{
if ( ! pnflag )
if ( firstid && ! secondid )
whitespace = TRUE;
}
else if ( strchr( "*,;[]", *cp ) == NULL )
{
#ifdef TESTING
printf( "*** NOT A FUNCTION BECAUSE OF <%c> ***\n", *cp );
#endif
return( FALSE );
}
}
else
{
if ( ! pnflag )
if ( ! firstid )
firstid = TRUE;
else if ( whitespace )
secondid = TRUE;
}
/* no parens at all? */
if ( ! pnflag )
{
#ifdef TESTING
printf( "*** NOT A FUNCTION BECAUSE THERE ARE NO PARENS ***\n" );
#endif
return( FALSE );
}
/* abnormal nesting result? */
if ( pnlevel != 0 )
{
#ifdef TESTING
printf( "*** NOT A FUNCTION BECAUSE PAREN NESTING IS BAD ***\n" );
#endif
return( FALSE );
}
/* bad id/whitespace sequence? */
if ( ! firstid || ! whitespace || ! secondid )
{
#ifdef TESTING
printf( "*** NOT A FUNCTION BECAUSE ID/WHITESPACE/PAREN SEQUENCE IS WRONG ***\n" );
#endif
return( FALSE );
}
/* 'else' keyword? */
if ( ( cp = strstr( s, "else" ) ) != NULL )
if ( cp == s || ! isid( *( cp - 1 ) ) )
if ( ! isid( *( cp + 4 ) ) )
{
#ifdef TESTING
printf( "*** NOT A FUNCTION BECAUSE OF 'ELSE' KEYWORD ***\n" );
#endif
return( FALSE );
}
/* 'return' keyword? */
if ( ( cp = strstr( s, "return" ) ) != NULL )
if ( cp == s || ! isid( *( cp - 1 ) ) )
if ( ! isid( *( cp + 6 ) ) )
{
#ifdef TESTING
printf( "*** NOT A FUNCTION BECAUSE OF 'RETURN' KEYWORD ***\n" );
#endif
return( FALSE );
}
#ifdef TESTING
printf( "FUNCTION->>> " );
#endif
return( TRUE );
}
/*=======================================================================*/